package com.seele.base.utils;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.seele.base.models.PingModel;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Description: 一个pingIP 地址的工具
 * Data: 2018/7/29 1:40
 *
 * @author: jimbo
 */
public class PingUtils {

    private static PingUtils mInstance;
    private HandlerThread mHandlerThread;
    private Handler mHandler;
    private ExecutorService service;
    private WeakReference<OnAddressResponseListener> mListener;

    private final int ONFLAG = 0X825;
    private int mCount = 0;

    private List<PingModel> mPingModel;




    public void setOnAddressResponseListener(OnAddressResponseListener listener) {
        mListener = new WeakReference<>(listener);

    }

    public interface OnAddressResponseListener {

        void onErrorAddress();

        void onSuccessAddress(String address);
    }

    public PingUtils init() {
        if (null == mHandlerThread) {
            mHandlerThread = new HandlerThread("select address");
        }
        mHandlerThread.start();
        if (null == mHandler) {
            mHandler = new android.os.Handler(mHandlerThread.getLooper(), mCallback);
        }
        if (null == mPingModel) {
            mPingModel = new ArrayList<>();
        }

        service = Executors.newFixedThreadPool(6);

        return this;
    }


    private Handler.Callback mCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case ONFLAG:
                    mCount--;
                    Object obj = msg.obj;
                    if (obj instanceof PingModel) {
                        PingModel model = (PingModel) obj;
                        mPingModel.add(model);
                    }
                    if (mCount == 0) {
                        handlerData();
                    }
                    break;
            }


            return false;
        }
    };

    /**
     * 处理数据
     */
    private void handlerData() {
        if (null != mPingModel && mPingModel.size() > 0) {
            //移除失败的地址
            for (int i = mPingModel.size() - 1; i >= 0; i--) {
                if (!mPingModel.get(i).isAvailable) {
                    mPingModel.remove(i);
                }
            }
            if (null!=mPingModel&&mPingModel.size()>0){
                PingModel model = Collections.min(mPingModel);
                if (null!=mListener){
                    mListener.get().onSuccessAddress(model.ip);
                }
            }else {
                if (null!=mListener){
                    mListener.get().onErrorAddress();
                }
            }
        }else {
            if (null!=mListener){
                mListener.get().onErrorAddress();
            }
        }


    }


    /**
     * 根据IP 地址组装models
     *
     * @param address
     * @return
     */
    private List<PingModel> getPingModes(List<String> address) {
        List<PingModel> modelList = null;
        if (null != address && address.size() > 0) {
            modelList = new ArrayList<>();
            for (String s : address) {
                PingModel model = new PingModel();
                model.ip = s;
                modelList.add(model);
            }
        }

        return modelList;
    }


    public void getOptimalAddress(List<String> address) {
        List<PingModel> pingModes = getPingModes(address);
        mCount = pingModes == null ? 0 : pingModes.size();
        if (mCount > 0) {
            for (final PingModel mPingMode : pingModes) {
                service.execute(new Runnable() {
                    @Override
                    public void run() {
                        init(mPingMode);

                    }
                });
            }
        }

    }

    public void getAddress(List<String> address) {
        List<PingModel> pingModes = getPingModes(address);
        mCount = pingModes == null ? 0 : pingModes.size();



    }


    public PingModel init(PingModel model) {
        String result = null;
        String delay = null;
        String lost = null;
        boolean isAvailable = false;
        Process process = null;
        BufferedReader successReader = null;
        BufferedReader errorReader = null;
        DataOutputStream dos = null;
        if (!TextUtils.isEmpty(model.ip) && !TextUtils.isEmpty(model.getPing())) {
            try {
                process = Runtime.getRuntime().exec(model.getPing());
                InputStream in = process.getInputStream();
                //成功
                successReader = new BufferedReader(
                        new InputStreamReader(in));
                // error
                errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

                String lineStr;

                while ((lineStr = successReader.readLine()) != null) {
                    //成功返回的数据
                    LogUtils.dTag(model.ip, "====successReader====:" + lineStr);

                    result = result + lineStr + "\n";
                    isAvailable = true;
                    if (lineStr.contains("packet loss")) {
                        LogUtils.dTag(model.ip, "=====Message=====" + lineStr.toString());
                        int i = lineStr.indexOf("received");
                        int j = lineStr.indexOf("%");
                        LogUtils.d("====丢包率====:" + lineStr.substring(i + 10, j + 1));
                        lost = lineStr.substring(i + 10, j + 1);
                    }

                    if (lineStr.contains("avg")) {
                        int i = lineStr.indexOf("/", 20);
                        int j = lineStr.indexOf(".", i);
                        LogUtils.dTag(model.ip, "====平均时延:====" + lineStr.substring(i + 1, j));
                        delay = lineStr.substring(i + 1, j);
//                    delay = delay + "ms";
                    }

                    while ((lineStr = errorReader.readLine()) != null) {
                        isAvailable = true;
                        LogUtils.dTag(model.ip, "==error======" + lineStr);
                        // tv_show.setText(lineStr);
                    }

                }

                model.isAvailable = isAvailable;
                model.result = result;
                if (TextUtils.isEmpty(delay)) {
                    delay = "0";
                }
                model.delay = Integer.parseInt(delay);
                model.lost = lost;
                Log.e("model:::", "delay::" + delay);
            } catch (Exception e) {
                LogUtils.dTag(model.ip, "==未知错误======");
                e.printStackTrace();
            }

        }


        Log.e("model:::", "" + model.toString());
        Message message = mHandler.obtainMessage(ONFLAG, model);
        mHandler.sendMessage(message);
        return model;
    }


}
